package com.kuaimacode.kframework.api.controller.user;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.kuaimacode.kframework.api.controller.BaseController;
import com.kuaimacode.kframework.api.jwt.JwtTokenUtil;
import com.kuaimacode.kframework.api.jwt.JwtUserFactory;
import com.kuaimacode.kframework.api.service.AliTokenService;
import com.kuaimacode.kframework.api.service.SysMessageService;
import com.kuaimacode.kframework.api.service.UserService;
import com.kuaimacode.kframework.api.service.sys.TokenBlackService;
import com.kuaimacode.kframework.api.vo.request.*;
import com.kuaimacode.kframework.api.vo.response.BaseLoginResp;
import com.kuaimacode.kframework.api.vo.response.CertifacateInfoResp;
import com.kuaimacode.kframework.api.vo.response.UserInfoResp;
import com.kuaimacode.kframework.api.vo.response.UserPartnerResp;
import com.kuaimacode.kframework.common.JsonResult;
import com.kuaimacode.kframework.component.ComponentUtil;
import com.kuaimacode.kframework.component.SmsRecordService;
import com.kuaimacode.kframework.constants.PageConstants;
import com.kuaimacode.kframework.enums.DeviceTypeEnum;
import com.kuaimacode.kframework.exception.ErrorEnum;
import com.kuaimacode.kframework.exception.ServerInternalErrorException;
import com.kuaimacode.kframework.mybatis.models.sys.SysMessage;
import com.kuaimacode.kframework.mybatis.models.sys.TokenBlack;
import com.kuaimacode.kframework.mybatis.models.user.User;
import com.kuaimacode.kframework.service.SysPushTokenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Optional;

@Slf4j
@RestController
@RequestMapping("/user")
@Api(tags = "用户", description = "用户相关api")
public class UserRestController extends BaseController {

    @Value("${jwt.header}")
    private String tokenHeader;
    @Autowired
    private UserService userService;
    @Autowired
    private SysMessageService messageService;
    @Autowired
    private SmsRecordService recordService;
    @Autowired
    private ComponentUtil componentUtil;
    @Autowired
    private SysPushTokenService pushTokenService;
    @Autowired
    private TokenBlackService tokenBlackService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private AliTokenService aliTokenService;


    @ApiOperation(value = "获取用户资料", notes = "获取当前登录用户资料")
    @RequestMapping(value = "user", method = RequestMethod.GET)
    public JsonResult<UserInfoResp> getAuthenticatedUser() {
        UserInfoResp infoResp = userService.getUserInfo(getUserId());
        //处理用户头像信息
        Optional.ofNullable(infoResp)
                .ifPresent(innerUser ->
                        innerUser.setAvatarUrl(componentUtil.convertImgUrl(innerUser.getAvatarUrl()))
                );
        return JsonResult.success(infoResp);
    }

    @ApiOperation(value = "修改个人信息", notes = "修改个人信息")
    @PostMapping("/updatePersonInfo")
    @ApiImplicitParam(name = "infoReq", value = "UpdatePersonInfoReq实体", required = true, dataType = "UpdatePersonInfoReq")
    public JsonResult updatePersonInfo(@RequestBody UpdatePersonInfoReq infoReq) {
        infoReq.setId(getUserId());
        return JsonResult.success(userService.updatePersonInfo(infoReq));
    }

    @ApiOperation(value = "校验验证码是否正确", notes = "校验验证码是否正确")
    @PostMapping("/checkValidCode")
    @ApiImplicitParam(name = "validCodeReq", value = "CheckValidCodeReq实体", required = true, dataType = "CheckValidCodeReq")
    public JsonResult checkValidCode(@Valid @RequestBody CheckValidCodeReq validCodeReq) {
        if (recordService.validVerifyCode(validCodeReq.getPhone(), validCodeReq.getVerifyCode())) {
            return JsonResult.success();
        } else {
            return JsonResult.failure(ErrorEnum.VERIFY_CODE_VALID_ERROR.getCode(),
                    ErrorEnum.VERIFY_CODE_VALID_ERROR.getMsg());
        }
    }

    @ApiOperation(value = "绑定手机号", notes = "绑定手机号")
    @GetMapping("/bindMobile")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mobile", value = "手机号", required = true, dataType = "string"),
            @ApiImplicitParam(name = "verifyCode", value = "验证码", required = true, dataType = "string")
    })
    public JsonResult<BaseLoginResp> bindMobile(@RequestParam String mobile, @RequestParam String verifyCode) {
        userService.bindMobile(mobile, verifyCode, getUserId());
        BaseLoginResp loginResp = new BaseLoginResp();
        User user = userService.getById(getUserId());
        loginResp.setToken(jwtTokenUtil.generateToken(JwtUserFactory.create(user, new ArrayList<>())));
        loginResp.setIsProtocol(user.getIsProtocol());
        return JsonResult.success(loginResp);
    }

    @ApiOperation(value = "更换手机号", notes = "更换手机号")
    @PostMapping("/updatePhone")
    @ApiImplicitParam(name = "req", value = "UpdatePhoneReq实体", required = true, dataType = "UpdatePhoneReq")
    public JsonResult<BaseLoginResp> updatePhone(@Valid @RequestBody UpdatePhoneReq req) {
        req.setId(getUserId());
        userService.updatePhone(req);
        BaseLoginResp loginResp = new BaseLoginResp();
        User user = userService.getById(getUserId());
        loginResp.setToken(jwtTokenUtil.generateToken(JwtUserFactory.create(user, new ArrayList<>())));
        loginResp.setIsProtocol(user.getIsProtocol());
        return JsonResult.success(loginResp);
    }

    @ApiOperation(value = "查询实名认证信息", notes = "查询实名认证信息")
    @PostMapping("/certifacateInfo")
    public JsonResult<CertifacateInfoResp> certifacateInfo() {
        return JsonResult.success(userService.certifacateInfo(getUserId()));
    }

    @ApiOperation(value = "用户同意协议接口", notes = "用户同意协议")
    @PostMapping("/agreeProtocol")
    public JsonResult agreeProtocol() {
        userService.agreeProtocol(getUserId());
        return JsonResult.success();
    }

    @ApiOperation(value = "获取用户消息列表", notes = "获取用户消息列表")
    @PostMapping("/getUserMessages/{userType}")
    @ApiImplicitParam(name = "userType", value = "消息类型 0 用户消息 1 师傅消息", required = true, dataType = "string", paramType = "path")
    public JsonResult<SysMessage> getUserMessages(@PathVariable Integer userType,
                                                  @RequestParam(value = "pageNum", defaultValue = PageConstants.PAGE_NUM_STR) int pageNum,
                                                  @RequestParam(value = "pageSize", defaultValue = PageConstants.PAGE_SIZE_STR) int pageSize) {
        return JsonResult.success(new PageInfo<>(messageService.getUserMessages(getUserId(), userType, pageNum, pageSize)));
    }


    @ApiOperation(value = "查询用户是否是合作商家", notes = "如果是，返回合作商家名称、地址、头像、经纬度、费用等信息；如果不是不返回信息")
    @GetMapping("/checkPartner")
    public JsonResult<UserPartnerResp> checkPartner() {
        UserPartnerResp infoResp = userService.getPartner(getUserId());
        //处理用户头像信息
        Optional.ofNullable(infoResp)
                .ifPresent(innerUser ->
                        innerUser.setPartnerAvatar(componentUtil.convertImgUrl(innerUser.getPartnerAvatar()))
                );
        return JsonResult.success(infoResp);
    }

    @ApiOperation(value = "申请为合作商家", notes = "申请为合作商家")
    @ApiImplicitParam(name = "req", value = "ApplyPartnerReq实体", required = true, dataType = "ApplyPartnerReq")
    @PostMapping("/applyPartner")
    public JsonResult<Boolean> applyPartner(@RequestBody ApplyPartnerReq applyPartnerReq) {
        log.info("apply partner params: {}", JSONObject.toJSONString(applyPartnerReq));
        return JsonResult.success(userService.applyPartner(applyPartnerReq, getUserId()));
    }

    @ApiOperation(value = "更新用户推送token信息", notes = "更新用户推送token信息")
    @ApiImplicitParam(name = "req", value = "UpdatePushTokenReq实体", required = true, dataType = "UpdatePushTokenReq")
    @PostMapping("/updatePushToken")
    public JsonResult updatePushToken(@RequestBody @Valid UpdatePushTokenReq pushTokenReq) {
        DeviceTypeEnum deviceTypeEnum;
        try {
            deviceTypeEnum = DeviceTypeEnum.valueOf(pushTokenReq.getDeviceType());
        } catch (IllegalArgumentException e) {
            throw new ServerInternalErrorException(ErrorEnum.PUSH_DEVICE_TYPE_ERROR);
        }
        pushTokenService.saveOrUpdate(getUserId(), pushTokenReq.getToken(), deviceTypeEnum);
        return JsonResult.success();
    }

    @ApiOperation(value = "更新用户推送别名信息", notes = "更新用户推送别名信息")
    @ApiImplicitParam(name = "req", value = "UpdatePushAliasReq实体", required = true, dataType = "UpdatePushAliasReq")
    @PostMapping("/updatePushAlias")
    public JsonResult updatePushAlias(@RequestBody @Valid UpdatePushAliasReq pushAliasReq) {
        DeviceTypeEnum deviceTypeEnum;
        try {
            deviceTypeEnum = DeviceTypeEnum.valueOf(pushAliasReq.getDeviceType());
        } catch (IllegalArgumentException e) {
            throw new ServerInternalErrorException(ErrorEnum.PUSH_DEVICE_TYPE_ERROR);
        }
        pushTokenService.saveOrUpdate(getUserId(), pushAliasReq.getAlias(), deviceTypeEnum);
        return JsonResult.success();
    }

    @ApiOperation(value = "读取消息", notes = "读取消息")
    @PostMapping("/readMessage/{messageId}")
    @ApiImplicitParam(name = "messageId", value = "消息ID", required = true, dataType = "string", paramType = "path")
    public JsonResult readMessage(@PathVariable Long messageId) {
        return JsonResult.success(messageService.readMessage(messageId, getUserId()));
    }

    @ApiOperation(value = "小程序更新formid", notes = "小程序更新formid")
    @GetMapping("/updateFormId")
    @ApiImplicitParam(name = "formIds", value = "formIds", required = true, dataType = "string")
    public JsonResult updateAppletsFormId(@RequestParam String formIds) {
        userService.updateAppletsFormId(formIds, getUserId());
        return JsonResult.success();
    }

    @ApiOperation(value = "登出", notes = "登出")
    @GetMapping(value = "logout")
    public JsonResult logout() {
        TokenBlack black = new TokenBlack();
        final String requestHeader = request.getHeader(this.tokenHeader);
        black.setToken(requestHeader.substring(7));
        tokenBlackService.save(black);
        return JsonResult.success();
    }

    @ApiOperation(value = "获取阿里token", notes = "获取阿里token")
    @GetMapping("/getAliToken")
    public JsonResult getAliToken() {
        return JsonResult.success(aliTokenService.getToken());
    }
}
